package flatlandRPGTest;

import org.lwjgl.input.Keyboard;
import flatlandRPG.TestableKeyboard;
import flatlandRPG.Building;
import java.awt.geom.Rectangle2D;
import flatlandRPG.GLPrimitive;
import flatlandRPG.Player;
import org.lwjgl.util.vector.Vector2f;

// -------------------------------------------------------------------------
/**
 * Tests the player class.
 *
 * @author evant
 * @version Apr 17, 2011
 */
public class PlayerTest
    extends GLRectangleTest
{
    private Player testPlayer;


    public void setUp()
    {
        super.setUp();
        testPlayer = (Player)getPrimitive();
        TestableKeyboard.clear();
    }


    public GLPrimitive getPrimitive()
    {
        return new Player();
    }


    // ----------------------------------------------------------
    /**
     * Tests that the player moves by the given vector.
     */
    public void testMove()
    {
        testPlayer.setLocation(new Vector2f(2, 2));
        testPlayer.move(new Vector2f(1, 2));

        assertEquals(3, testPlayer.getX(), 0.0001);
        assertEquals(4, testPlayer.getY(), 0.0001);
    }


    // ----------------------------------------------------------
    /**
     * Tests that the bounding box for the player is correct.
     */
    public void testGetBounds()
    {
        Rectangle2D bounds = testPlayer.getBounds();

        assertEquals(-0.05f, bounds.getX(), 0.0001f);
        assertEquals(-0.05f, bounds.getY(), 0.0001f);
        assertEquals(0.1f, bounds.getWidth(), 0.0001f);
        assertEquals(0.1f, bounds.getHeight(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that collision detector works correctly.
     */
    public void testCollision()
    {
        Building building =
            new Building(
                new Vector2f(0.1f, 0.2f),
                new Vector2f(0.2f, 0.2f),
                new Vector2f(0.2f, 0.1f),
                new Vector2f(0.1f, 0.1f));

        assertFalse(building.collidedWith(testPlayer));

        testPlayer.move(new Vector2f(0, 0.1f));
        testPlayer.move(new Vector2f(0.1f, 0));

        assertTrue(building.collidedWith(testPlayer));
    }


    // ----------------------------------------------------------
    /**
     * Tests that the player doesn't move when there is no collision.
     */
    public void testPlayerNoCollisionResponse()
    {
        Building building =
            new Building(
                new Vector2f(0.1f, 0.2f),
                new Vector2f(0.2f, 0.2f),
                new Vector2f(0.2f, 0.1f),
                new Vector2f(0.1f, 0.1f));

        testPlayer.move(new Vector2f(0, 0.1f));
        testPlayer.collision(building);

        assertEquals(0, testPlayer.getX(), 0.0001f);
        assertEquals(0.1f, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that the player moves correctly in response to a collision.
     */
    public void testPlayerCollisionResponse()
    {
        Building building =
            new Building(
                new Vector2f(0.1f, 0.2f),
                new Vector2f(0.2f, 0.2f),
                new Vector2f(0.2f, 0.1f),
                new Vector2f(0.1f, 0.1f));

        testPlayer.move(new Vector2f(0, 0.1f));
        testPlayer.move(new Vector2f(0.1f, 0));
        testPlayer.collision(building);

        assertEquals(0, testPlayer.getX(), 0.0001f);
        assertEquals(0.1f, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that when there is a collision, the player moves back multiple
     * times until there is no collision.
     */
    public void testPlayerMultipleMovementCollisonResponse()
    {
        Building building =
            new Building(
                new Vector2f(0.1f, 0.2f),
                new Vector2f(0.2f, 0.2f),
                new Vector2f(0.2f, 0.1f),
                new Vector2f(0.1f, 0.1f));

        testPlayer.move(new Vector2f(0, 0.1f));
        testPlayer.move(new Vector2f(0.1f, 0));
        testPlayer.move(new Vector2f(0.05f, 0));
        testPlayer.collision(building);

        assertEquals(0, testPlayer.getX(), 0.0001f);
        assertEquals(0.1f, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that pressing the right arrow key moves the player right.
     */
    public void testMoveRight()
    {
        TestableKeyboard.setKeyDown(Keyboard.KEY_RIGHT);
        testPlayer.doLogic();

        assertEquals(Player.SPEED, testPlayer.getX(), 0.0001f);
        assertEquals(0, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that pressing the left arrow key moves the player right.
     */
    public void testMoveLeft()
    {
        TestableKeyboard.setKeyDown(Keyboard.KEY_LEFT);
        testPlayer.doLogic();

        assertEquals(-Player.SPEED, testPlayer.getX(), 0.0001f);
        assertEquals(0, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that pressing the up arrow key moves the player right.
     */
    public void testMoveUp()
    {
        TestableKeyboard.setKeyDown(Keyboard.KEY_UP);
        testPlayer.doLogic();

        assertEquals(0, testPlayer.getX(), 0.0001f);
        assertEquals(Player.SPEED, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that pressing the down arrow key moves the player right.
     */
    public void testMoveDown()
    {
        TestableKeyboard.setKeyDown(Keyboard.KEY_DOWN);
        testPlayer.doLogic();

        assertEquals(0, testPlayer.getX(), 0.0001f);
        assertEquals(-Player.SPEED, testPlayer.getY(), 0.0001f);
    }


    // ----------------------------------------------------------
    /**
     * Tests that the player doesn't move when no keys are pressed.
     */
    public void testNoMovement()
    {
        testPlayer.doLogic();

        assertEquals(0, testPlayer.getX(), 0.0001f);
        assertEquals(0, testPlayer.getY(), 0.0001f);
    }
}
